package com.fwtai.service;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.fwtai.bean.PageFormData;
import com.fwtai.bean.UploadFile;
import com.fwtai.core.AsyncDao;
import com.fwtai.quartz.AffirmDelivery;
import com.fwtai.quartz.AutoDelivery;
import com.fwtai.quartz.MallDeleteOrder;
import com.fwtai.quartz.QuartzDelayed;
import com.fwtai.service.api.ApiShareService;
import com.fwtai.tool.IdBuilder;
import com.fwtai.tool.ToolClient;
import com.fwtai.tool.ToolImage;
import com.fwtai.tool.ToolString;
import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SplittableRandom;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 异步处理,注意，这里的异步方法，只能在本类的自身之外调用，在本类调用是无效的!!!,即在别的类调用即可
 * @注意 需要在启动类添加开启异步处理@EnableAsync注解类
 * @作者 田应平
 * @版本 v1.0
 * @创建时间 2020-04-10 20:11
 * @QQ号码 444141300
 * @Email service@yinlz.com
 * @官网 <url>http://www.fwtai.com</url>
 */
@Component
public class AsyncService{

  private final AsyncDao asyncDao;

  private final ApiShareService apiShareService;

  private final ThreadPoolTaskExecutor taskHanderExecutor;

  public AsyncService(final AsyncDao asyncDao,final ThreadPoolTaskExecutor taskHanderExecutor,final ApiShareService apiShareService){
    this.asyncDao = asyncDao;
    this.taskHanderExecutor = taskHanderExecutor;
    this.apiShareService = apiShareService;
  }

  @Async("taskHanderExecutor")
  public void updateLogin(final String username){
    CompletableFuture.runAsync(()->{
      asyncDao.updateSucceed(username);
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void addSmsRecord(final PageFormData formData,final ArrayList<HashMap<String,Object>> listParams){
    CompletableFuture.runAsync(()->{
      formData.put("lists",listParams);
      asyncDao.addSmsRecord(formData);
    },taskHanderExecutor);
  }

  // 删除封面
  @Async("taskHanderExecutor")
  public void delKnowledgeCover(final String coverPath){
    CompletableFuture.runAsync(()->{
      if(coverPath != null && coverPath.length() >0){
        ToolClient.delFileByThread(coverPath);
      }
    },taskHanderExecutor);
  }

  /*更新知识的浏览量*/
  @Async("taskHanderExecutor")
  public void updateBrowse(final String kid){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.updateBrowse(kid);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  /*更新微信号的视频的浏览量*/
  @Async("taskHanderExecutor")
  public void updateVideoBrowse(final String kid){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.updateVideoBrowse(kid);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  /**咨询被回复*/
  @Async("taskHanderExecutor")
  public void sendReplay(final String advisoryId){}

  /**用户一对一咨询律师通知*/
  @Async("taskHanderExecutor")
  public void consult(final String phone,final String userId,final String lawyerId){}

  @Async("taskHanderExecutor")
  public void lawyerToUser(final String lawyerId,final String userId){}

  /**咨询大厅的用户咨询律师通知*/
  @Async("taskHanderExecutor")
  public void advisory(final String phone){}

  /**案件被预委托*/
  @Async("taskHanderExecutor")
  public void sendAccept(final String caseId){}

  @Async("taskHanderExecutor")
  public void delAsync(final Long kid){
    final ThreadPoolExecutor executor = new ThreadPoolExecutor(
      Runtime.getRuntime().availableProcessors()*2,10240,1L,TimeUnit.SECONDS,new ArrayBlockingQueue<>(5120),new ThreadPoolExecutor.CallerRunsPolicy()
    );
    try {
      executor.execute(()->{
        //处理业务
      });
    }finally{
      executor.shutdown();//释放线程池
    }
  }

  /**若咨询的用户删除自己的咨询时连同已回复的咨询一起删除,todo 请参考此代码*/
  @Async("taskHanderExecutor")
  public void delReplay(final Long kid){
    TaskAsync.getInstance().execute(()-> asyncDao.delReplay(kid));
  }

  /**案件当事人确定意向委托律师时发送短信通知律师*/
  @Async("taskHanderExecutor")
  public void sendLawyer(final String userId){}

  @Async("taskHanderExecutor")
  public void authResultApproved(final String userId){
    //final String phone = asyncDao.getAuthUserName(userId);
    //ToolSms.authResultApproved(phone);
  }

  @Async("taskHanderExecutor")
  public void authResultFail(final String userId){
    //final String phone = asyncDao.getAuthUserName(userId);
    //ToolSms.authResultFail(phone);
  }

  @Async("taskHanderExecutor")
  public void partnerResultApproved(final String userId){
    //final String phone = asyncDao.getAuthUserName(userId);
    //ToolSms.partnerResultApproved(phone);
  }

  @Async("taskHanderExecutor")
  public void partnerResultFail(final String userId){
    //final String phone = asyncDao.getAuthUserName(userId);
    //ToolSms.partnerResultFail(phone);
  }

  /**个体申请认证成功-短信*/
  @Async("taskHanderExecutor")
  public void individualSucceed(final String userId){
    //ToolSms.individualSucceed(asyncDao.getAuthUserName(userId));
  }

  /**个体申请认证失败-短信*/
  @Async("taskHanderExecutor")
  public void individualFail(final String userId){
    //ToolSms.individualFail(asyncDao.getAuthUserName(userId));
  }

  /**批量站内认证信息*/
  @Async("taskHanderExecutor")
  public void addBatchAuth(final ArrayList<Long> list,final String details){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          final ArrayList<HashMap<String,Object>> arrayList = new ArrayList<>(list.size());
          list.forEach(item->{
            final HashMap<String,Object> map = new HashMap<>(3);
            map.put("kid",new IdBuilder().getId121L());
            map.put("details",details);
            map.put("user_id",item);
            arrayList.add(map);
          });
          asyncDao.addBatchAuth(arrayList);
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  //更新已读
  @Async("taskHanderExecutor")
  public void updateReadInform(final String kid,final String loginId){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.updateReadInform(kid,loginId);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  @Async("taskHanderExecutor")
  public void delCaseInform(final String kid){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.delCaseInform(kid);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  @Async("taskHanderExecutor")
  public void getDetails(final String kid){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          final List<Map<String,Object>> list = asyncDao.getDetails(kid);
          asyncDao.delDetails(kid);
          final ArrayList<String> pathImg = new ArrayList<>();
          final ArrayList<String> pathAttach = new ArrayList<>();
          for(int i = list.size() - 1; i >= 0; i--){
            final String type = String.valueOf(list.get(i).get("type"));
            final String path = String.valueOf(list.get(i).get("path"));
            switch (type){
              case "1":
                pathAttach.add(path);
                break;
              case "2":
                pathImg.add(path);
                break;
              default:
                break;
            }
          }
          if(pathImg.size() > 0){
            for(int i = pathImg.size() - 1; i >= 0; i--){
              ToolClient.delFileByThread(pathImg.get(i));
            }
          }
          if(pathAttach.size() > 0){
            for(int i = pathAttach.size() - 1; i >= 0; i--){
              ToolClient.delFileByThread(pathAttach.get(i));
            }
          }
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  /**self=1时说明的律师自己发布的案件,否则普通账号或合伙人发布的案件*/
  @Async("taskHanderExecutor")
  public void addInforms(final int self,final String caseId,final String title){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          final List<String> list = self == 1 ? asyncDao.getPartysLawyer(caseId) : asyncDao.getPartysUser(caseId);
          final ArrayList<HashMap<String,String>> arrayList = new ArrayList<HashMap<String,String>>();
          for(int i = list.size() - 1; i >= 0; i--){
            final HashMap<String,String> map = new HashMap<String,String>(2);
            map.put("userId",list.get(i));//案件当事人或发布人
            map.put("details","88888888,4,"+caseId+"您的案件["+title+"]有新的进展,请查看详情");
            map.put("partner_add_auth",String.valueOf(new IdBuilder().getId121L()));
            arrayList.add(map);
          }
          if(arrayList.size() > 0){
            asyncDao.addPartys(arrayList);
          }
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  @Async("taskHanderExecutor")
  public void addHome(final PageFormData formData){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.addHome(formData);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  //绑定手机号|账号
  @Async("taskHanderExecutor")
  public void updateWechat(final PageFormData formData){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(() -> {
      try {
        asyncDao.updateWechat(formData);
      } catch (final Exception ignored){
      }finally{
        threadPool.shutdown();//释放线程池
      }
    });
  }

  /**
   * 订单记录,对账用的
  */
  @Async("taskHanderExecutor")//后期要使用独立的数据库
  public void addMaterialOrderLog(final long orderId,final long out_trade_no,final Long loginId,final Object buyerName,final Long lawyerId,final Object lawyerName,final Object amount,final String details){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(() -> {
      try {
        final PageFormData formData = new PageFormData();
        formData.put("kid",new IdBuilder().getId121L());
        formData.put("loginId",loginId);//下单人userId
        formData.put("buyer_name",buyerName);//下单人账号
        formData.put("orderId",orderId);
        formData.put("out_trade_no",out_trade_no);
        formData.put("amount",amount);
        formData.put("user_id",lawyerId);//资料文档发布人id
        formData.put("user_name",lawyerName);//资料文档发布人账号
        formData.put("details",details);
        asyncDao.addMaterialOrderLog(formData);
      } catch (final Exception ignored){
      }finally{
        threadPool.shutdown();//释放线程池
      }
    });
  }

  @Async("taskHanderExecutor")//后期要使用独立的数据库
  public void addServiceOrderLog(final long orderId,final long out_trade_no,final Long loginId,final String buyerName,final long user_id,final String userName,final Object amount,final String details){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(() -> {
      try {
        final PageFormData formData = new PageFormData();
        formData.put("kid",new IdBuilder().getId121L());
        formData.put("loginId",loginId);//下单人购买人id
        formData.put("buyer_name",buyerName);//下单人购买人账号
        formData.put("orderId",orderId);
        formData.put("out_trade_no",out_trade_no);
        formData.put("amount",amount);
        formData.put("user_id",user_id);//服务发布人id
        formData.put("user_name",userName);//服务发布人账号
        formData.put("details",details);
        asyncDao.addServiceOrderLog(formData);
      } catch (final Exception ignored){
      }finally{
        threadPool.shutdown();//释放线程池
      }
    });
  }

  /**
   * 全路径文件
   * @param fullLocal
  */
  @Async("taskHanderExecutor")
  public void delLocalFile(final String fullLocal){
    ToolClient.delFileByThread(fullLocal);
  }

  /**
   * 删除文件,
   * @param json 是json对象格式的数据
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2022/5/16 18:47
  */
  @Async("taskHanderExecutor")
  public void delFile(final String json){
    final HashMap<String,String> map = ToolString.parseJsonObject(json);
    map.forEach((k,v)->{
      if(k.equals("fullPath")){
        ToolClient.delFileByThread(v);
      }
    });
  }

  /**
   * 添加或编辑时code不是200时需要删除的已上传的单个文件
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2022/7/15 22:36
  */
  @Async("taskHanderExecutor")
  public void delFileForAddOrEdit(final PageFormData formData,final String key){
    final String json = formData.getString(key);
    final HashMap<String,String> map = ToolString.parseJsonObject(json);
    ToolClient.delFileByThread(map.get("fullPath"));
  }

  /**
   * 添加或编辑时code不是200时需要删除的已上传的多个文件
   * @param
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2022/7/15 22:36
  */
  @Async("taskHanderExecutor")
  public void delFileForAddOrEdit(final PageFormData formData,final ArrayList<String> lists){
    lists.forEach(item->{
      final String json = formData.getString(item);
      final HashMap<String,String> map = ToolString.parseJsonObject(json);
      ToolClient.delFileByThread(map.get("fullPath"));
    });
  }

  /**
   * 删除文件,
   * @param json 是json数组格式的数据
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2022/5/16 18:47
  */
  public void delFileList(final String json){
    final ArrayList<HashMap<String,String>> list = ToolString.parseJsonArray(json);
    list.forEach(item->{
      item.forEach((k,v)->{
        if(k.equals("fullPath")){
          ToolClient.delFileByThread(v);
        }
      });
    });
  }

  /*删除律师认证时删除对应的认证图片*/
  @Async("taskHanderExecutor")
  public void delAuthImage(final String imgPath){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(() -> {
      try {
        final String[] arrs = imgPath.split(",");
        for(int i = arrs.length - 1; i >= 0; i--){
          ToolClient.delFileByThread(arrs[i]);
        }
      } catch (final Exception ignored){
      }finally{
        threadPool.shutdown();//释放线程池
      }
    });
  }

  @Async("taskHanderExecutor")
  public void updateReadForUserLawyer(final PageFormData formData){
    CompletableFuture.runAsync(()->{
      asyncDao.updateReadForUserLawyer(formData);
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void addMerchantUser(final long merchantId,final long buyerId){
    CompletableFuture.runAsync(()->{
      final PageFormData formData = new PageFormData();
      formData.put("kid",new IdBuilder().getId121L());
      formData.put("merchant_id",merchantId);
      formData.put("buyer_id",buyerId);
      asyncDao.addMerchantUser(formData);
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void sendSMS(final long merchantId){
    CompletableFuture.runAsync(()->{
      final List<String> list = asyncDao.getMerchantPhones(merchantId);//是否开启短信通知
      if(list != null && list.size() > 0){
        System.out.println("短信通知的号码:"+list);
      }
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void updateReadForLawyerUser(final PageFormData formData){
    CompletableFuture.runAsync(()->{
      asyncDao.updateReadForLawyerUser(formData);
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void delServiceAd(final PageFormData formData){
    CompletableFuture.runAsync(()->{
      final String adImgs = asyncDao.getServiceAd(formData.getLong("kid"));
      delFile(adImgs);
    },taskHanderExecutor).thenRunAsync(()->{
      asyncDao.delServiceAd(formData);
    },taskHanderExecutor);
  }

  @Async("taskHanderExecutor")
  public void addMerchant(final String userId){
    final String json = apiShareService.queryCode(userId);
    final HashMap<String,String> map = ToolString.parseJsonObject(json);
    final String data = map.get("data");
    final String code = ToolString.parseJsonObject(data).get("code");
    final PageFormData formData = new PageFormData();
    formData.put("code",code);
    formData.put("user_id",Long.parseLong(userId));
    formData.put("enabled",0);
    CompletableFuture.runAsync(()->{
      asyncDao.addMerchant(formData);
    },taskHanderExecutor);
  }

  //todo 不需要加 @Async("taskHanderExecutor")
  public void updateMaxRatio(final HashMap<String,Object> params){
    asyncDao.updateMaxRatio(params);
  }

  //单个字段上传多个文件
  @Deprecated
  public void handlerFile(final PageFormData formData,final ArrayList<UploadFile> listFiles,final Map<String,List<String>> maps,final String... keys){
    for(int x = keys.length - 1; x >= 0; x--){
      final String fieldKey = keys[x];
      final List<String> lists = maps.get(fieldKey);
      if(lists != null){
        final JSONObject result = new JSONObject(lists.size()+2);
        for(int y = lists.size() - 1; y >= 0; y--){
          final String value = lists.get(y);
          for(int z = listFiles.size() - 1; z >= 0; z--){
            final UploadFile uploadFile = listFiles.get(z);
            final String name = uploadFile.getName();
            if(name.equals(value)){
              final JSONObject object = new JSONObject(5);
              object.put("fullPath",uploadFile.getFullPath());
              object.put("urlFile",uploadFile.getUrlFile());
              object.put("fileSize",uploadFile.getFileSize());
              object.put("originalName",uploadFile.getOriginalName());
              object.put("currentDir",uploadFile.getCurrentDir());
              result.put(name,object);
              if(y==0){
                result.put("total",lists.size());
                result.put("fieldKey",fieldKey);
              }
              break;
            }
          }
        }
        formData.put(fieldKey,result.toString());
      }
    }
  }

  /**
   * 处理单个文件域上传多个文件是转为json数组,final
   * @param keys 存储json数组的字段集合
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2025-08-06 18:31:51
  */
  public void handlerFiles(final PageFormData formData,final ArrayList<UploadFile> listFiles,final String... keys){
    final ArrayList<String> listName = new ArrayList<>(listFiles.size());
    listFiles.forEach(uploadFile -> {
      listName.add(uploadFile.getName());
    });
    for(int x = keys.length - 1; x >= 0; x--){
      final JSONArray array = new JSONArray(keys.length);
      final String fieldKey = keys[x];
      final List<String> lists = listName.stream().collect(Collectors.groupingBy(itemValue -> itemValue.substring(0,itemValue.length() - 1))).get(fieldKey);
      if(lists != null){
        for(int y = lists.size() - 1; y >= 0; y--){
          final String value = lists.get(y);
          for(int z = listFiles.size() - 1; z >= 0; z--){
            final UploadFile uploadFile = listFiles.get(z);
            final String name = uploadFile.getName();
            if(name.equals(value)){
              final JSONObject json = new JSONObject(5);
              json.put("fullPath",uploadFile.getFullPath());
              json.put("fileSize",uploadFile.getFileSize());
              json.put("urlFile",uploadFile.getUrlFile());
              json.put("originalName",uploadFile.getOriginalName());
              json.put("currentDir",uploadFile.getCurrentDir());
              array.add(json);
              break;
            }
          }
        }
        if(!array.isEmpty()){
          formData.put(fieldKey,array.toString());
        }
      }
    }
  }

  //文件域的单文件上传处理
  public void handlerFile(final PageFormData formData,final ArrayList<UploadFile> listFiles,final ArrayList<String> lists){
    listFiles.forEach(uploadFile -> {
      final String name = uploadFile.getName();
      for(int i = lists.size() - 1; i >= 0; i--){
        final String value = lists.get(i);
        if(name.equals(value)){
          final JSONObject json = new JSONObject(5);
          json.put("fullPath",uploadFile.getFullPath());
          json.put("urlFile",uploadFile.getUrlFile());
          json.put("fileSize",uploadFile.getFileSize());
          json.put("currentDir",uploadFile.getCurrentDir());
          json.put("originalName",uploadFile.getOriginalName());
          formData.put(name,json.toString());
          break;
        }
      }
    });
  }

  public String compressPic(final PageFormData formData,final ArrayList<UploadFile> listFiles,final ThreadPoolTaskExecutor taskExecutor,final int type,final String... fields){
    for(int i = fields.length - 1; i >= 0; i--){
      final String field = fields[i];
      final String jsonValue = (String)formData.get(field);
      final JSONObject jsonObject = ToolString.parseJsonObj(jsonValue);
      final String fullPath = jsonObject.getString("fullPath");
      final HashMap<String,Integer> widthHeight = ToolImage.getWidthHeight(fullPath);
      if(widthHeight == null){
        for(int y = listFiles.size() - 1; y >= 0; y--){
          final UploadFile uploadFile = listFiles.get(y);
          delFileFullPath(uploadFile.getFullPath());//删除文件
        }
        return ToolClient.jsonValidateField("请选择上传图片文件");
      }else{
        final String current = jsonObject.getString("currentDir");
        final String compressDir = "compress/";
        final String currentDir = current+compressDir;
        final String urlFile = jsonObject.getString("urlFile");
        final int lastIndexOf = urlFile.lastIndexOf("/");
        final String urlDir = urlFile.substring(0,lastIndexOf)+"/"+compressDir;
        final String sub = urlFile.substring(lastIndexOf+1);
        final String[] split = sub.split("\\.");
        final String reduceFullPath = currentDir+sub;
        ToolImage.compress(taskExecutor,fullPath,reduceFullPath,type,split[1]);
        final String reduceUrl = urlDir+sub;
        jsonObject.put("reduceFullPath",reduceFullPath);
        jsonObject.put("reduceUrl",reduceUrl);
        formData.put(field,jsonObject.toString());
      }
    }
    return null;
  }

  public String compressPic(final PageFormData formData,final ArrayList<UploadFile> listFiles,final ThreadPoolTaskExecutor taskExecutor,final int type,final HashMap<String,String> fields){
    for(final String key : fields.keySet()){
      final String field = fields.get(key);
      final String jsonValue = (String)formData.get(field);
      final JSONObject jsonObject = ToolString.parseJsonObj(jsonValue);
      final String fullPath = jsonObject.getString("fullPath");
      final HashMap<String,Integer> widthHeight = ToolImage.getWidthHeight(fullPath);
      if(widthHeight == null){
        for(int y = listFiles.size() - 1; y >= 0; y--){
          final UploadFile uploadFile = listFiles.get(y);
          delFileFullPath(uploadFile.getFullPath());//删除文件
        }
        return ToolClient.jsonValidateField("请选择上传图片文件");
      }else{
        final String current = jsonObject.getString("currentDir");
        final String compressDir = "compress/";
        final String currentDir = current+compressDir;
        final String urlFile = jsonObject.getString("urlFile");
        final int lastIndexOf = urlFile.lastIndexOf("/");
        final String urlDir = urlFile.substring(0,lastIndexOf)+"/"+compressDir;
        final String sub = urlFile.substring(lastIndexOf+1);
        final String[] split = sub.split("\\.");
        final String reduceFullPath = currentDir+sub;
        ToolImage.compress(taskExecutor,fullPath,reduceFullPath,type,split[1]);
        final String reduceUrl = urlDir+sub;
        formData.put(key,"{\"fullPath\":\""+fullPath+"\",\"reduceFullPath\":\""+reduceFullPath+"\",\"reduceUrl\":\""+reduceUrl+"\",\"urlFile\":\""+jsonObject.getString("urlFile")+"\",\"currentDir\":\""+currentDir+"\"}");
        formData.put(field,jsonObject.toString());
      }
    }
    return null;
  }

  /**删除图片全路径字符串*/
  @Async("taskHanderExecutor")
  public void delFileFullPath(final String fullPath){
    new AsyncHandler<>().asyncConsumer(()->{
      ToolClient.delFileByThread(fullPath);
    });
  }

  /**删除图片json对象字符串,单文件上传*/
  @Async("taskHanderExecutor")
  public void delFileJsonObject(final String jsonObject){
    new AsyncHandler<>().asyncConsumer(()->{
      ToolClient.delFileByThread(ToolString.parseJsonObject(jsonObject).get("fullPath"));
    });
  }

  /**删除图片json对象字符串(json里含json),多文件上传*/
  @Async("taskHanderExecutor")
  public void delFileJsonObjects(final String jsonObject){
    new AsyncHandler<>().asyncConsumer(()->{
      final HashMap<String,String> map = ToolString.parseJsonObject(jsonObject);
      final int total = Integer.parseInt(map.get("total"));
      final String key = map.get("fieldKey");
      for(int i = total - 1; i >= 0; i--){
        final String values = map.get(key + i);
        final HashMap<String,String> hashMap = ToolString.parseJsonObject(values);
        ToolClient.delFileByThread(hashMap.get("fullPath"));
      }
    });
  }

  /**删除图片json数组字符串*/
  @Async("taskHanderExecutor")
  public void delFileJsonArray(final String jsonArray){
    new AsyncHandler<>().asyncConsumer(()->{
      final ArrayList<HashMap<String,String>> list = ToolString.parseJsonArray(jsonArray);
      for(int i = list.size() - 1; i >= 0; i--){
        ToolClient.delFileByThread(list.get(i).get("fullPath"));
      }
    });
  }

  @Async("taskHanderExecutor")
  public void addConsultRecord(final PageFormData formData){
    final ExecutorService threadPool = Executors.newCachedThreadPool();
    threadPool.execute(new Runnable(){
      @Override
      public void run(){
        try {
          asyncDao.addConsultRecord(formData);
        } catch (final Exception ignored){
        }finally{
          threadPool.shutdown();//释放线程池
        }
      }
    });
  }

  @Async("taskHanderExecutor")
  public void addActivityRecord(final long user_id,final long activity_id,final long order_id,final long store_id){
    final HashMap<String,Long> params = new HashMap<>(3);
    params.put("user_id",user_id);
    params.put("activity_id",activity_id);
    params.put("order_id",order_id);
    params.put("store_id",store_id);
    asyncDao.addActivityRecord(params);
  }

  /**支付成功后推送发货信息到微信*/
  @Async("taskHanderExecutor")
  public void addPushDeliverTask(final long outTradeNo,final String transactionId,final String openid){
    final String jobName = String.valueOf(outTradeNo);
    final String values = outTradeNo+","+transactionId+","+openid;
    final JobDetail jobDetail = JobBuilder.newJob(QuartzDelayed.class).usingJobData(QuartzDelayed.dateKey,values).withIdentity(jobName,QuartzDelayed.groupName).build();
    final SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,QuartzDelayed.groupName).startAt(new Date(new Date().getTime()+1000 * 60 * 5))
      .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMinutes(new SplittableRandom().nextInt(3,10))//每隔(3到10之间的随机数)分钟执行一次
        .withRepeatCount(3)).build();
    //创建调度器Scheduler
    try {
      final Scheduler scheduler = new StdSchedulerFactory().getScheduler();
      //执行
      scheduler.scheduleJob(jobDetail,trigger);
      scheduler.start();
    } catch (final SchedulerException ignored){}
  }

  /**
   * 微信支付的订单及积分订单也要自动确认收货的`任务`,自动发货步骤1:加入到定时任务,服务接口更新时也要调用本方法，也就是重新加入到任务队列;微信支付的订单;积分支付的订单
   * @param type 1是微信支付;2是积分支付
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2024/1/26 20:15
  */
  @Async("taskHanderExecutor")//todo final,直接参考此
  public void addDeliveryAuto(final Long outTradeNo,final int type,final Long time,final String transactionId){
    final String jobName = String.valueOf(outTradeNo);
    final JobDetail jobDetail = JobBuilder.newJob(AutoDelivery.class).usingJobData(AutoDelivery.dateKey,outTradeNo+","+type+","+transactionId).withIdentity(jobName,AutoDelivery.groupName).build();
    final SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,AutoDelivery.groupName).startAt(new Date(new Date().getTime()+(time == null ? 259200000 : time)))//1000 * 60 * 60 * 24 * 3 = 259200000,默认是 3 天后执行
      .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMinutes(new SplittableRandom().nextInt(10,30))//每隔(10到30之间的随机数)分钟执行一次
        .withRepeatCount(2)).build();
    //创建调度器Scheduler
    try {
      final Scheduler scheduler = new StdSchedulerFactory().getScheduler();
      //执行
      scheduler.scheduleJob(jobDetail,trigger);
      scheduler.start();
    } catch (final SchedulerException ignored){}
  }

  /**
   * 微信支付的订单及积分订单也要自动确认收货的`任务`,自动发货步骤1:加入到定时任务,服务接口更新时也要调用本方法，也就是重新加入到任务队列;微信支付的订单;积分支付的订单
   * @param type 1是微信支付;2是积分支付
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2024/1/26 20:15
  */
  @Async("taskHanderExecutor")//todo final,直接参考此
  public void addAutoDelivery(final Long outTradeNo,final int type,final Long time,final String transactionId){
    final String jobName = String.valueOf(outTradeNo);
    final JobDetail jobDetail = JobBuilder.newJob(AffirmDelivery.class).usingJobData(AffirmDelivery.dateKey,outTradeNo+","+type+","+transactionId).withIdentity(jobName,AffirmDelivery.groupName).build();
    final SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,AffirmDelivery.groupName).startAt(new Date(new Date().getTime()+(time == null ? 604800000 : time)))//1000 * 60 * 60 * 24 * 7 = 604800000,默认是 7 天后执行
      .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMinutes(new SplittableRandom().nextInt(5,8))//每隔(5到8之间的随机数)分钟执行一次
        .withRepeatCount(2)).build();
    //创建调度器Scheduler
    try {
      final Scheduler scheduler = new StdSchedulerFactory().getScheduler();
      //执行
      scheduler.scheduleJob(jobDetail,trigger);
      scheduler.start();
    } catch (final SchedulerException ignored){}
  }

  /**
   * 通用的定时任务
   * @param time 剩余时间要执行的时间,单位秒
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2024/12/19 16:13
   */
  @Async("taskHanderExecutor")//todo final,直接参考此
  public void addTask(final Class<? extends Job> jobClass,final String dateKey,final long outTradeNo,final Long time){
    final String jobName = String.valueOf(outTradeNo);
    final String groupName = jobClass.getName();
    final JobDetail jobDetail = JobBuilder.newJob(jobClass).usingJobData(dateKey,outTradeNo).withIdentity(jobName,groupName).build();
    final SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,groupName).startAt(new Date(new Date().getTime()+time))
      .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMinutes(new SplittableRandom().nextInt(5,8))//每隔(5到8之间的随机数)分钟执行一次
        .withRepeatCount(2)).build();
    //创建调度器Scheduler
    try {
      final Scheduler scheduler = new StdSchedulerFactory().getScheduler();
      //执行
      scheduler.scheduleJob(jobDetail,trigger);
      scheduler.start();
    } catch (final SchedulerException ignored){}
  }

  @Async("taskHanderExecutor")//todo 可以创建多个就可以达到像微信支付通知回调的那个,1,5,10,30,60...之类的通知,此处是移除一个任务（仅在手动删除的成功后才能删除定时任务,也就是 rows > 0 才能调用本方法）
  public void delMallOrderInfo(final long out_trade_no){
    final String jobName = String.valueOf(out_trade_no);
    final JobDetail jobDetail = JobBuilder.newJob(MallDeleteOrder.class).usingJobData(MallDeleteOrder.dateKey,out_trade_no).withIdentity(jobName,MallDeleteOrder.groupName).build();
    final long time = 60 * 1000 * 35;//todo 35分钟
    final SimpleTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobName,MallDeleteOrder.groupName).startAt(new Date(new Date().getTime()+time))//35分钟后执行
      .withSchedule(SimpleScheduleBuilder.simpleSchedule()
        .withIntervalInMinutes(new SplittableRandom().nextInt(8,16))//每隔(8到16之间的随机数)分钟执行一次
        .withRepeatCount(2)).build();//重复次数(总共执行3次,因为32分钟后执行1次,加上重复执行2次,共3次)
    //创建调度器Scheduler
    try {
      final Scheduler scheduler = new StdSchedulerFactory().getScheduler();
      //执行
      scheduler.scheduleJob(jobDetail,trigger);
      scheduler.start();
    } catch (final SchedulerException ignored){}
  }

  @Async("taskHanderExecutor")
  public void updateProductPv(final long kid,final ThreadPoolTaskExecutor taskExecutor){
    CompletableFuture.runAsync(()->{
      asyncDao.updateProductPv(kid);
    },taskExecutor);
  }

  @Async("taskHanderExecutor")
  public void updateGoodsPv(final long kid,final ThreadPoolTaskExecutor executor){
    CompletableFuture.runAsync(()->{
      asyncDao.updateGoodsPv(kid);
    },executor);
  }

  @Async("taskHanderExecutor")
  public void editCheckTime(final HashMap<String,Object> params,final ThreadPoolTaskExecutor executor){
    CompletableFuture.runAsync(()->{
      asyncDao.editCheckTime(params);
    },executor);
  }

  @Async("taskHanderExecutor")
  public void updateCheckTotal(final String code,final ThreadPoolTaskExecutor executor){
    CompletableFuture.runAsync(()->{
      asyncDao.updateCheckTotal(code);
    },executor);
  }
}